// 根据授权码从模拟api获取token,刷新token以及告知第三方解绑
import { AbstractPlatform } from '../AbstractPlatform';
import {getBrandConfig} from "../getBrandConfig";
import axios from "axios";
import {MockThirdParty} from "../../mock/MockThirdParty";
import {AppDataSource} from "../../config/database";
import {BranchAccount} from "../../entity/BranchAccount";
import { AccessToken } from '../../entity/Accesstoken';
import { MideaNotifyBody } from '../../api/notify.route';


export class MideaMock extends AbstractPlatform {
    private mockThirdParty: MockThirdParty;
    private config = getBrandConfig("midea");

    constructor() {
        super();
        const config = getBrandConfig('midea');
        this.mockThirdParty = new MockThirdParty(config.app_id, config.app_secret);
    }

    async exchangeToken(code: string): Promise<{ access_token: string; expires_in: number }> {
        this.logExchange('midea', true);
        try {
            const response = await this.mockThirdParty.exchangeToken(code);

            return {
                access_token: response.access_token,
                expires_in: response.expires_in
            };
        } catch (e: any) {
            throw new Error(`Failed to exchange token: ${e.message}`);
        }
    }

    async revokeToken(token: string): Promise<void> {
        try {
            await this.mockThirdParty.revokeToken(token);
        } catch (error: any) {
            throw new Error(`Failed to revoke token: ${error.message}`);
        }
    }


    async refreshToken(userId: string, oldToken: string): Promise<{ access_token: string; expires_in: number }> {
        try {
            const response = await this.mockThirdParty.refreshToken(userId, oldToken);

            return {
                access_token: response.access_token,
                expires_in: response.expires_in,
            };
        } catch (error: any) {
            throw new Error(`Failed to refresh token: ${error.message}`);
        }
    }


    async getDeviceList(accessToken: string): Promise<{
        did: string;
        name: string;
        type: string;
        online: boolean;
    }[]> {
        const url = 'http://localhost:3001/midea/devices';
        const clientId = this.config.app_id;

        // 生成唯一的 reqId（使用时间戳）
        const reqId = Date.now().toString();

        // 创建带参数的 URL
        const urlWithParams = new URL(url);
        urlWithParams.searchParams.append('reqId', reqId.toString());

        const res = await fetch(url, {
            method: 'GET',
            headers: {
                Authorization: `Bearer ${accessToken}`,
                ClientId: clientId
            }
        });

        const json = await res.json();

        if (res.status !== 200 || json.code !== 200) {
            throw new Error(`获取美的设备列表失败: ${json.message || res.status}`);
        }

        const applianceList = json.data.applianceList || [];

        return applianceList.map((item: any) => ({
            did: item.virtualId,
            name: item.name,
            type: item.type,
            online: item.online
        }));

    }


    async subscribeDevice(accessToken: string, deviceId: string): Promise<void> {
        const reqId = Date.now().toString();
        const url = 'http://localhost:3001/midea/device/subscribe';

        const res = await fetch(url, {
            method: 'POST',
            headers: {
                Authorization: accessToken,
                ClientId: this.config.app_id,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                reqId,
                applianceCode: deviceId
            })
        });

        const json = await res.json();

        if (res.status !== 200) {
            throw new Error(`Midea订阅失败：HTTP状态码 ${res.status}`);
        }

        if (json.code === 1300) {
            throw new Error(`Midea订阅失败：设备不存在`);
        }

        if (json.code === 1006) {
            throw new Error(`Midea订阅失败：用户验证失败`);
        }

        console.log(`[SUBSCRIBE] Midea 设备 ${deviceId} 订阅成功 (reqId: ${reqId})`);
    }


    async revokeDeviceSubscription(userId: string, deviceId: string): Promise<void> {
        const reqId = Date.now().toString();
        const tokenRepo = AppDataSource.getRepository(BranchAccount);
        const record = await tokenRepo.findOne({where: {userId, brand: 'midea'}});

        if (!record) throw new Error(`未找到美的授权信息`);

        const res = await fetch('http://localhost:3001/midea/device/subscribe/cancel', {
            method: 'POST',
            headers: {
                Authorization: record.token,
                ClientId: this.config.app_id,
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({
                reqId,
                applianceCode: deviceId
            })
        });

        const json = await res.json();

        if (res.status !== 200) {
            throw new Error(`Midea取消订阅失败: ${res.status}`);
        }

        if (json.code === 1300) {
            throw new Error(`设备不存在`);
        } else if (json.code === 1006) {
            throw new Error(`用户验证失败`);
        }

        console.log(`[UNSUB] Midea 设备 ${deviceId} 取消订阅成功`);
    }

  // 生成传感器模拟数据
  private generateSensorData(deviceId: string): Record<string, any> {
    const now = new Date();
    const deviceType = deviceId.split('_')[1];
  
    switch(deviceType) {
    
      // 空气质量检测仪
      case 'air_quality':
        return {
          pm25: this.getRandomInt(0, 500),
          temperature: this.getRandomFloat(-10, 60, 1),
          humidity: this.getRandomInt(0, 100),
          time: now.toISOString()
        };
    
      // 空调
      case 'ac':
        return {
          online: Math.random() > 0.1, // 90%在线率
          target_temperature: this.getRandomFloat(16, 30, 1),
          fan_speed: ['low', 'medium', 'high', 'auto'][this.getRandomInt(0, 3)],
          mode: ['cool', 'heat', 'dry', 'fan'][this.getRandomInt(0, 3)],
          power: Math.random() > 0.5 ? 'ON' : 'OFF'
        };
    
      // 加湿器
      case 'humidifier':
        const power = this.getRandomInt(0, 1);
        return {
          online: Math.random() > 0.1,
          power: power ? 1 : 0,
          status: power ? 
            ['running', 'paused'][this.getRandomInt(0, 1)] : 'off',
          mode: ['auto', 'sleep', 'strong'][this.getRandomInt(0, 2)],
          target_humidity: this.getRandomInt(30, 80)
        };

      // 除湿器
      case 'dehumidifier':
        return {
          online: Math.random() > 0.1,
          power: this.getRandomInt(0, 1) ? 1 : 0,
          status: this.getRandomInt(0, 1) ? 
            ['running', 'paused'][this.getRandomInt(0, 1)] : 'off',
          mode: ['auto', 'sleep', 'dry'][this.getRandomInt(0, 2)],
          target_humidity: this.getRandomInt(30, 80)
        };

      // 空气净化器
      case 'purifier':
        return {
          online: Math.random() > 0.1,
          power: this.getRandomInt(0, 1) ? 1 : 0,
          status: this.getRandomInt(0, 1) ? 
            ['running', 'paused'][this.getRandomInt(0, 1)] : 'off',
          mode: ['auto', 'silent', 'strong'][this.getRandomInt(0, 2)],
          fan_level: this.getRandomInt(1, 3), // 1-3级风速
        };
    
      // 默认返回基础状态
      default:
        return {
          online: Math.random() > 0.1,
          power: Math.random() > 0.5 ? 'ON' : 'OFF',
          time: now.toISOString()
        };
    }
  }

  //美的设备状态推送方法
  async pushMideaDeviceStatus(
    deviceId: string,
    userId: string,
    properties: Record<string, any>
  ): Promise<void> {
    const notifyUrl = 'http://localhost:3000/api/midea/notify';
  
    try {
      // 严格匹配服务端接口的MideaNotifyBody格式
      const requestBody: MideaNotifyBody = {
        applianceCode: deviceId,
        userId,
        properties
      };

      const response = await axios.post(notifyUrl, requestBody);

      if (response.data.code !== 200) {
        throw new Error(`推送失败: ${response.data.message}`);
      }
    
      console.log(`[Midea] 设备 ${deviceId} 状态推送成功`, properties);
    } catch (err) {
      if (err instanceof Error) {
        console.error(`[Midea] 状态推送失败:`, err.message);
      } else {
        console.error(`[Midea] 状态推送失败:`, err);
      }
      throw new Error('推送服务不可用');
    }
  }

  // 添加设备控制方法
async controlDevice(
  accessToken: string,
  reqId: string,
  applianceId: string,
  control: { operation: string; value: any }
): Promise<{
  reqId: string;
  status: { operation: string; status: any; result: number };
}> {
  // 验证access_token
  const tokenRepo = AppDataSource.getRepository(AccessToken);
  const tokenRecord = await tokenRepo.findOne({ 
    where: { token: accessToken, appId: this.config.app_id }
  });

  if (!tokenRecord || tokenRecord.expiresAt < new Date()) {
    throw new Error('1006 用户验证失败');
  }

  // 检查设备是否存在
  const devices = await this.getDeviceList(accessToken);
  if (!devices.some(d => d.did === applianceId)) {
    throw new Error('1300 设备不存在');
  }

  // 模拟属性验证
  if (!['power', 'mode', 'target_temperature', 'fan_speed'].includes(control.operation)) {
    throw new Error('1002 参数非法');
  }

  // 推送状态变更（格式转换）
  await this.pushMideaDeviceStatus(applianceId, tokenRecord.userId, {
    [control.operation]: control.value
  });

  return {
    reqId,
    status: {
      operation: control.operation,
      status: control.value,
      result: 1 // 总是返回成功
    }
  };
}


  // 辅助方法
  private getRandomInt(min: number, max: number): number {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  private getRandomFloat(min: number, max: number, decimals: number): number {
    const value = Math.random() * (max - min) + min;
    return parseFloat(value.toFixed(decimals));
  }
}
